package com.eugene.scheduler;

import android.app.AlertDialog;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Color;
import android.preference.PreferenceManager;
import android.text.format.DateFormat;
import android.view.View;
import android.widget.RemoteViews;
import android.widget.Toast;

import java.text.DateFormatSymbols;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class SchedulerWidget extends AppWidgetProvider {
    private static final String ACTION_PREVIOUS_MONTH
            = "com.example.android.scheduler.action.PREVIOUS_MONTH";
    private static final String ACTION_NEXT_MONTH
            = "com.example.android.scheduler.action.NEXT_MONTH";
    private static final String ACTION_RESET_MONTH
            = "com.example.android.scheduler.action.RESET_MONTH";
    private static final String ACTION_DATE_CLICK
            = "com.example.android.scheduler.action.DATE_CLICK";
    private static final String ACTION_SETTINGS
            = "com.example.android.scheduler.action.SETTINGS";
    private static final String ACTION_UPDATE
            = "com.example.android.scheduler.action.APPWIDGET_UPDATE";

    private final static long MILLISECS_PER_DAY = 24 * 60 * 60 * 1000;

    private static final String PREF_MONTH = "month";
    private static final String PREF_YEAR = "year";

    // settings
    public static boolean showChanges = false;
    public static boolean show2014Holidays = true;
    public static boolean showUserChanges = false;
    public static Calendar beginDate = new GregorianCalendar(2014,0,1);
    public static int workDays = 2;
    public static int restDays = 2;
    public static int theme = ColorProvider.Style.Notebook.getValue();

    private ColorProvider colors = new ColorProvider();

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        DateInfo.context = context;
        super.onUpdate(context, appWidgetManager, appWidgetIds);

        for (int appWidgetId : appWidgetIds) {
            drawWidget(context, appWidgetId);
        }
    }

    private void redrawWidgets(Context context) {
        int[] appWidgetIds = AppWidgetManager.getInstance(context).getAppWidgetIds(
                new ComponentName(context, SchedulerWidget.class));
        for (int appWidgetId : appWidgetIds) {
            drawWidget(context, appWidgetId);
        }
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);

        DateInfo.context = context;

        String action = intent.getAction();

        if (ACTION_PREVIOUS_MONTH.equals(action)) {
            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
            Calendar cal = Calendar.getInstance();
            int thisMonth = sp.getInt(PREF_MONTH, cal.get(Calendar.MONTH));
            int thisYear = sp.getInt(PREF_YEAR, cal.get(Calendar.YEAR));
            cal.set(Calendar.DAY_OF_MONTH, 1);
            cal.set(Calendar.MONTH, thisMonth);
            cal.set(Calendar.YEAR, thisYear);
            cal.add(Calendar.MONTH, -1);
            sp.edit()
                    .putInt(PREF_MONTH, cal.get(Calendar.MONTH))
                    .putInt(PREF_YEAR, cal.get(Calendar.YEAR))
                    .apply();
            redrawWidgets(context);

        } else if (ACTION_NEXT_MONTH.equals(action)) {
            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
            Calendar cal = Calendar.getInstance();
            int thisMonth = sp.getInt(PREF_MONTH, cal.get(Calendar.MONTH));
            int thisYear = sp.getInt(PREF_YEAR, cal.get(Calendar.YEAR));
            cal.set(Calendar.DAY_OF_MONTH, 1);
            cal.set(Calendar.MONTH, thisMonth);
            cal.set(Calendar.YEAR, thisYear);
            cal.add(Calendar.MONTH, 1);
            sp.edit()
                    .putInt(PREF_MONTH, cal.get(Calendar.MONTH))
                    .putInt(PREF_YEAR, cal.get(Calendar.YEAR))
                    .apply();
            redrawWidgets(context);

        } else if (ACTION_RESET_MONTH.equals(action)) {
            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
            sp.edit().remove(PREF_MONTH).remove(PREF_YEAR).apply();
            redrawWidgets(context);
        } else if (ACTION_SETTINGS.equals(action)) {
            Intent activ = new Intent(context, CalendarSettings.class);
            activ.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(activ);
        } else if (ACTION_UPDATE.equals(action)) {
            onDisabled(context);
            redrawWidgets(context);
        }  else if (ACTION_DATE_CLICK.equals(action)) {
            SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
            String str = intent.getType();
            Date date = sdf.parse(str, new ParsePosition(0));
            DateDialog.date = date;
            //Toast.makeText(context, date.toString(), Toast.LENGTH_SHORT).show();

            Intent activ = new Intent(context, DateDialog.class);
            activ.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(activ);
        }
    }

    @Override
    public void onDisabled(Context context){
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
        sp.edit().putBoolean("showChanges", showChanges)
                .putInt("workDays", workDays)
                .putInt("restDays", restDays)
                .putLong("beginDate", beginDate.getTimeInMillis())
                .putBoolean("show2014Holidays",show2014Holidays)
                .putBoolean("showUserChanges",showUserChanges)
                .putInt("theme", theme)
                .apply();
    }

    @Override
    public void onEnabled(Context context){
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
        showChanges = sp.getBoolean("showChanges", false);
        workDays = sp.getInt("workDays", 2);
        restDays = sp.getInt("restDays", 2);
        beginDate.setTimeInMillis(sp.getLong("beginDate", beginDate.getTimeInMillis()));
        show2014Holidays = sp.getBoolean("show2014Holidays", true);
        showUserChanges = sp.getBoolean("showUserChanges", false);
        theme = sp.getInt("theme",ColorProvider.Style.Notebook.getValue());
    }

    //@Override
    //@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    // public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager,
    //         int appWidgetId, Bundle newOptions) {
    //super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
    //     drawWidget(context, appWidgetId);
    // }

    private void drawWidget(Context context, int appWidgetId) {
        onEnabled(context);
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
        Resources res = context.getResources();
        // Bundle widgetOptions = appWidgetManager.getAppWidgetOptions(appWidgetId);
        boolean shortMonthName = false;
        boolean mini = false;
        int numWeeks = 6;
        // if (widgetOptions != null) {
        //int minWidthDp = widgetOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH);
        //int minHeightDp = widgetOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT);
        // shortMonthName = minWidthDp <= res.getInteger(R.integer.max_width_short_month_label_dp);
        // mini = minHeightDp <= res.getInteger(R.integer.max_height_mini_view_dp);
        // if (mini) {
        // numWeeks = minHeightDp <= res.getInteger(R.integer.max_height_mini_view_1_row_dp)
        //            ? 1 : 2;
        // }
        // }

        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
        RemoteViews rv = new RemoteViews(context.getPackageName(), colors.getResourse(ColorProvider.Resource.MainWidget));

        Calendar cal = Calendar.getInstance();
        cal.setFirstDayOfWeek(Calendar.MONDAY);
        int today = cal.get(Calendar.DAY_OF_YEAR);
        int todayYear = cal.get(Calendar.YEAR);
        int thisMonth;
        if (!mini) {
            thisMonth = sp.getInt(PREF_MONTH, cal.get(Calendar.MONTH));
            int thisYear = sp.getInt(PREF_YEAR, cal.get(Calendar.YEAR));
            cal.set(Calendar.DAY_OF_MONTH, 1);
            cal.set(Calendar.MONTH, thisMonth);
            cal.set(Calendar.YEAR, thisYear);
        } else {
            thisMonth = cal.get(Calendar.MONTH);
        }

        String[] months_short = {"Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"};
        String[] months_long = {"Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"};

        shortMonthName = false;
        rv.setTextViewText(R.id.month_label, shortMonthName ? months_short[thisMonth] : months_long[thisMonth] +
                DateFormat.format(shortMonthName ? " 'yy" : " yyyy", cal));

        if (!mini) {
            cal.set(Calendar.DAY_OF_MONTH, 1);
            int monthStartDayOfWeek = cal.get(Calendar.DAY_OF_WEEK) - 1;
            if(monthStartDayOfWeek == 0) monthStartDayOfWeek = 7;
            cal.add(Calendar.DAY_OF_MONTH, 1 - monthStartDayOfWeek);
        } else {
            int todayDayOfWeek = cal.get(Calendar.DAY_OF_WEEK) - 1;
            if(todayDayOfWeek == 0) todayDayOfWeek = 7;
            cal.add(Calendar.DAY_OF_MONTH, 1 - todayDayOfWeek);
        }

        rv.removeAllViews(R.id.calendar);

        RemoteViews headerRowRv = new RemoteViews(context.getPackageName(),
                R.layout.row_header);
        DateFormatSymbols dfs = DateFormatSymbols.getInstance();
        //String[] weekdays = dfs.getShortWeekdays();
        String[] weekdays = ColorProvider.getWeekDays();
        for (int day = Calendar.SUNDAY; day <= Calendar.SATURDAY; day++) {
            RemoteViews dayRv = new RemoteViews(context.getPackageName(), R.layout.cell_header);
            dayRv.setTextViewText(android.R.id.text1, weekdays[day]);
            headerRowRv.addView(R.id.row_container, dayRv);
            dayRv.setInt(android.R.id.text1, "setBackgroundResource", colors.getColor(ColorProvider.Position.BackHeader));
            dayRv.setInt(android.R.id.text1, "setTextColor", context.getResources().getColor(colors.getColor(ColorProvider.Position.TextHeader)));
        }
        rv.addView(R.id.calendar, headerRowRv);

        RemoteViews empt = new RemoteViews(context.getPackageName(), colors.getResourse(ColorProvider.Resource.LineH));
        empt.setInt(android.R.id.background, "setBackgroundResource", colors.getColor(ColorProvider.Position.Background));
        rv.addView(R.id.calendar, empt);

        for (int week = 0; week < numWeeks; week++) {
            RemoteViews rowRv = new RemoteViews(context.getPackageName(), R.layout.row_week);

            RemoteViews empty = new RemoteViews(context.getPackageName(), colors.getResourse(ColorProvider.Resource.LineV));
            empty.setInt(android.R.id.background, "setBackgroundResource", colors.getColor(ColorProvider.Position.Background));
            rowRv.addView(R.id.row_container, empty);

            for (int day = 0; day < 7; day++) {
                boolean inMonth = cal.get(Calendar.MONTH) == thisMonth;
                boolean inYear  = cal.get(Calendar.YEAR) == todayYear;
                boolean isToday = inYear && inMonth && (cal.get(Calendar.DAY_OF_YEAR) == today);


                RemoteViews cellRv = new RemoteViews(context.getPackageName(), colors.getResourse(ColorProvider.Resource.Cell));
                cellRv.setTextViewText(android.R.id.text1, Integer.toString(cal.get(Calendar.DAY_OF_MONTH)));

                boolean hday = isHoliday(cal);
                int colorB = hday ? colors.getColor(ColorProvider.Position.BackHoliday) : colors.getColor(ColorProvider.Position.BackDay);
                int colorT = hday ? colors.getColor(ColorProvider.Position.TextHoliday) : colors.getColor(ColorProvider.Position.TextDay);

                if(inMonth){
                    colorB = hday ? colors.getColor(ColorProvider.Position.BackHolidayTM) : colors.getColor(ColorProvider.Position.BackDayTM);
                    colorT = hday ? colors.getColor(ColorProvider.Position.TextHolidayTM) : colors.getColor(ColorProvider.Position.TextDayTM);
                }
                if(isToday){
                    colorB = colors.getColor(ColorProvider.Position.BackToday);
                    if(!hday) colorT = colors.getColor(ColorProvider.Position.TextToday);
                }

                cellRv.setInt(android.R.id.text1, "setBackgroundResource", colorB);
                cellRv.setInt(android.R.id.text1, "setTextColor", context.getResources().getColor(colorT));

                SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
                cellRv.setOnClickPendingIntent(android.R.id.text1,
                        PendingIntent.getBroadcast(context, 0,
                                new Intent(context, SchedulerWidget.class)
                                        .setAction(ACTION_DATE_CLICK).setType(sdf.format(cal.getTime())),
                                PendingIntent.FLAG_UPDATE_CURRENT));

                rowRv.addView(R.id.row_container, cellRv);

                RemoteViews emp = new RemoteViews(context.getPackageName(), colors.getResourse(ColorProvider.Resource.LineV));
                emp.setInt(android.R.id.background, "setBackgroundResource", colors.getColor(ColorProvider.Position.Background));
                rowRv.addView(R.id.row_container, emp);

                cal.add(Calendar.DAY_OF_MONTH, 1);
            }
            rv.addView(R.id.calendar, rowRv);

            RemoteViews emp2 = new RemoteViews(context.getPackageName(), colors.getResourse(ColorProvider.Resource.LineH));
            emp2.setInt(android.R.id.background, "setBackgroundResource", colors.getColor(ColorProvider.Position.Background));
            rv.addView(R.id.calendar, emp2);
        }

        rv.setViewVisibility(R.id.prev_month_button, mini ? View.GONE : View.VISIBLE);
        rv.setOnClickPendingIntent(R.id.prev_month_button,
                PendingIntent.getBroadcast(context, 0,
                        new Intent(context, SchedulerWidget.class)
                                .setAction(ACTION_PREVIOUS_MONTH),
                        PendingIntent.FLAG_UPDATE_CURRENT));
        rv.setViewVisibility(R.id.next_month_button, mini ? View.GONE : View.VISIBLE);
        rv.setOnClickPendingIntent(R.id.next_month_button,
                PendingIntent.getBroadcast(context, 0,
                        new Intent(context, SchedulerWidget.class)
                                .setAction(ACTION_NEXT_MONTH),
                        PendingIntent.FLAG_UPDATE_CURRENT));
        rv.setOnClickPendingIntent(R.id.month_label,
                PendingIntent.getBroadcast(context, 0,
                        new Intent(context, SchedulerWidget.class)
                                .setAction(ACTION_RESET_MONTH),
                        PendingIntent.FLAG_UPDATE_CURRENT));
        rv.setViewVisibility(R.id.month_bar, numWeeks <= 1 ? View.GONE : View.VISIBLE);
        rv.setOnClickPendingIntent(R.id.settings_button,
                PendingIntent.getBroadcast(context, 0,
                        new Intent(context, SchedulerWidget.class)
                                .setAction(ACTION_SETTINGS),
                        PendingIntent.FLAG_UPDATE_CURRENT));
        appWidgetManager.updateAppWidget(appWidgetId, rv);
    }

    static boolean isHoliday(Calendar cal){
        if(showUserChanges){
            int user = DateInfo.getDateInfo(cal.getTime());
            if(user!=-1){
                return user == 1;
            }
        }

        if(showChanges){
            cal.set(Calendar.HOUR_OF_DAY, 1);
            cal.set(Calendar.MINUTE, 1);
            cal.set(Calendar.SECOND, 0);
            cal.set(Calendar.MILLISECOND, 0);
            Date dt1 = new Date(cal.getTimeInMillis());

            beginDate.set(Calendar.HOUR_OF_DAY, 1);
            beginDate.set(Calendar.MINUTE, 1);
            beginDate.set(Calendar.SECOND, 0);
            beginDate.set(Calendar.MILLISECOND, 0);
            Date dt2 = new Date(beginDate.getTimeInMillis());

            long days = (dt1.getTime() - dt2.getTime()) / MILLISECS_PER_DAY;
            int d = (int)days;
            if(d<0) d = -d+restDays-1;
            if(d%(workDays + restDays) >= workDays) return true;
        }
        else{
            int day = cal.get(Calendar.DAY_OF_WEEK);
            if(day == Calendar.SATURDAY || day == Calendar.SUNDAY) return true;
            if(fromSchedule(cal)==2) return true;
        }
        return false;
    }

    static int fromSchedule(Calendar cal){
        if(!show2014Holidays) return 0;
        int month = cal.get(Calendar.MONTH); // 0 to 11
        int day = cal.get(Calendar.DAY_OF_MONTH); // 1 to 31 ?
        switch(month){
            case Calendar.JANUARY: if(day<=8) return 2; break;
            case Calendar.FEBRUARY: if(day==24) return 1; break;
            case Calendar.MARCH: if(day==7) return 1; if(day==10) return 2; break;
            case Calendar.APRIL: if(day==30) return 1; break;
            case Calendar.MAY: if(day<=2 || day==9) return 2; if(day==8) return 1; break;
            case Calendar.JUNE: if(day == 12 || day == 13) return 2; if(day==11) return 1; break;
            case Calendar.NOVEMBER: if(day==3 || day ==4) return 2; break;
            case Calendar.DECEMBER: if(day==31) return 1; break;
        }

        return 0;
    }
}